package org.odst.transformer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument;
import org.odst.formula.Formula;
import org.odst.formula.FormulaController;
import org.odst.formula.FormulaControllerImpl;
import org.odst.formula.ListRange;
import org.odst.util.SheetHelper;

/**
 * Represents excel workbook
 * @author Leonid Vysochyn
 * @author Cyril PODER
 */
public class Workbook {
    protected final Log log = LogFactory.getLog(getClass());

    List<Sheet> sheets = new ArrayList<Sheet>();
	
	private Map<String, List<String>> sheetMapping;
	
	public void setSheetMapping(Map<String, List<String>> sheetMapping) {
		this.sheetMapping = sheetMapping;
	}
	
	public Map<String, List<String>> getSheetMapping() {
		return sheetMapping;
	}

	/**
     * POI Excel workbook object
     */
    OdfSpreadsheetDocument oooWorkbook;

    FormulaController formulaController;

    Configuration configuration = new Configuration();

    public Workbook(OdfSpreadsheetDocument oooWorkbook) {
        this.oooWorkbook = oooWorkbook;
    }

    public Workbook(OdfSpreadsheetDocument oooWorkbook, Configuration configuration) {
        this.oooWorkbook = oooWorkbook;
        this.configuration = configuration;
    }

    public Workbook(OdfSpreadsheetDocument oooWorkbook, List<Sheet> sheets) {
        this.oooWorkbook = oooWorkbook;
        this.sheets = sheets;
    }

    public Workbook(OdfSpreadsheetDocument oooWorkbook, List<Sheet> sheets, Configuration configuration) {
        this.oooWorkbook = oooWorkbook;
        this.sheets = sheets;
        this.configuration = configuration;
    }

    public OdfSpreadsheetDocument getOooWorkbook() {
        return oooWorkbook;
    }

    public void setHssfWorkbook(OdfSpreadsheetDocument oooWorkbook) {
        this.oooWorkbook = oooWorkbook;
    }

    public void addSheet(Sheet sheet){
        sheets.add( sheet );
        sheet.setWorkbook( this );
    }

    public void initSheetNames(){
        for (int i = 0; i < sheets.size(); i++) {
            Sheet sheet = (Sheet) sheets.get(i);
            sheet.initSheetName();
        }
    }

    public Map<String, ListRange> getListRanges(){
        Map<String, ListRange> listRanges = new HashMap<String, ListRange>();
        for (int i = 0; i < sheets.size(); i++) {
            Sheet sheet = (Sheet) sheets.get(i);
            listRanges.putAll( sheet.getListRanges() );
        }
        return listRanges;
    }

    public List<Formula> findFormulas(){
        List<Formula> formulas = new ArrayList<Formula>();
        for (int i = 0; i < sheets.size(); i++) {
            Sheet sheet = (Sheet) sheets.get(i);
            formulas.addAll( SheetHelper.findFormulas( sheet, sheetMapping ) );
        }
        return formulas;
    }

    public Map<String, List<Formula>> createFormulaSheetMap(){
        Map<String, List<Formula>> formulasMap = new HashMap<String, List<Formula>>();
        for (int i = 0; i < sheets.size(); i++) {
            Sheet sheet = (Sheet) sheets.get(i);
            List<Formula> formulas = SheetHelper.findFormulas( sheet, sheetMapping );
            if (!formulasMap.containsKey(sheet.getSheetName()))
            	formulasMap.put(sheet.getSheetName(), new ArrayList<Formula>());
            formulasMap.get(sheet.getSheetName()).addAll(formulas);
            for (String sheetName : sheetMapping.keySet())
            	if (!sheetName.equals(sheet.getSheetName()))
	            	for (Formula formula : formulas)
	            		if (!formula.isInline() && formula.getFormula().contains(sheetName)) {
	                        if (!formulasMap.containsKey(sheetName))
	                        	formulasMap.put(sheetName, new ArrayList<Formula>());
	                        formulasMap.get(sheetName).add(formula);
	            		}
            			
        }
        return formulasMap;
    }

    public FormulaController createFormulaController(){
        formulaController = new FormulaControllerImpl( this );
        return formulaController;
    }

    public FormulaController getFormulaController() {
        return formulaController;
    }


    public List<Sheet> getSheets() {
        return sheets;
    }

    public int getNumberOfSheets(){
        return sheets.size();
    }

    public Sheet getSheetAt(int sheetNo){
        return (Sheet) sheets.get( sheetNo );
    }

    public void removeSheetAt(int sheetNo){
        oooWorkbook.getTableList().get(sheetNo).remove();
        sheets.remove( sheetNo );
    }

}
